#include "mid_pwm0.h"
#include "M480.h"

uint32_t g_pwm0_inited;


uint32_t PWM0_Init(uint32_t freq, uint8_t duty)
{

	/* Enable IP module clock */
    CLK_EnableModuleClock(EPWM0_MODULE);

    /* EPWM clock frequency is set double to PCLK: select EPWM module clock source as PLL */
    CLK_SetModuleClock(EPWM0_MODULE, CLK_CLKSEL2_EPWM0SEL_PLL, (uint32_t)NULL);


    /* Set PA.5 multi-function pin for EPWM0 channel 0 */
    SYS->GPB_MFPL = (SYS->GPB_MFPL & ~SYS_GPB_MFPL_PB5MFP_EPWM0_CH0) | SYS_GPB_MFPL_PB5MFP_EPWM0_CH0;

	/*
      Configure EPWM0 channel 0 init period and duty(up counter type).
      Period is PLL / (prescaler * (CNR + 1))
      Duty ratio = (CMR) / (CNR + 1)
      Period = 48 MHz / (2 * (19 + 1)) = 1200000 Hz
      Duty ratio = (100) / (19 + 1) = 50%
    */

    /* EPWM0 channel 0 frequency is 1800Hz, duty 50%, */
    //EPWM_ConfigOutputChannel(EPWM0, 0, 1200, 50);
    EPWM_ConfigOutputChannel(EPWM0, 0, freq, duty);

    /* Enable output of EPWM0 channel 0 */
    EPWM_EnableOutput(EPWM0, EPWM_CH_0_MASK);

    /* Start EPWM counter */
    EPWM_Start(EPWM0, EPWM_CH_0_MASK);
	
    g_pwm0_inited = 1;
	return 0;
}

uint32_t PWM0_DeInit(void)
{
	if (g_pwm0_inited == 0) return 1;
	
	/* Stop EPWM counter */
    EPWM_Stop(EPWM0, EPWM_CH_0_MASK);
    /* Disable output of EPWM0 channel 0 */
    EPWM_DisableOutput(EPWM0, EPWM_CH_0_MASK);
    
    g_pwm0_inited = 0;
	return 0;
}


/**
 * @brief       Calculate the comparator value of new duty by configured period
 *
 * @param       epwm                  The pointer of the specified EPWM module
 *
 * @param       u32ChannelNum        EPWM channel number. Valid values are between 0~5
 *
 * @param       u32DutyCycle         Target generator duty cycle percentage. Valid range are between 0 ~ u32CycleResolution.
 *                                   If u32CycleResolution is 100, and u32DutyCycle is 10 means 10%, 20 means 20% ...
 *
 * @param       u32CycleResolution   Target generator duty cycle resolution. The value in general is 100.
 *
 * @return      The comparator value by new duty cycle
 */
static uint32_t CalNewDutyCMR(EPWM_T *epwm, uint32_t u32ChannelNum, uint32_t u32DutyCycle, uint32_t u32CycleResolution)
{
    return (u32DutyCycle * (EPWM_GET_CNR(epwm, u32ChannelNum) + 1) / u32CycleResolution);
}

uint32_t PWM0_SetDuty(uint32_t u32NewDutyCycle)
{
	if (g_pwm0_inited == 0) return 1;
	
	/* Get new comparator value by call CalNewDutyCMR() */
    uint32_t u32NewCMR = CalNewDutyCMR(EPWM0, 0, u32NewDutyCycle, 100);
    /* Set new comparator value to register */
    EPWM_SET_CMR(EPWM0, 0, u32NewCMR);
	
	return 0;
}

